﻿// This software is the confidential and proprietary information of NetBay.
// Such confidential information should not be disclosed.
// NetBay copyright(c) 2012

#region

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Globalization;
using System.IO;
using System.Net.Mail;
using System.Reflection;
using System.Text.RegularExpressions;
using NetBay.Core.BusinessEntities;
using NetBay.Core.BusinessEntities.Workflow;
using NetBay.Core.Log;
using NetBay.Core.Mail.SMTP.Assync;
using Rio.Doc.Business.Repository;
using Rio.Flow.Business.Repository;
using Rio.Framework.RioManager;
using Rio.Workflow.Runtime.Enums;
using Rio.Workflow.Runtime.Extentions;

#endregion

namespace Rio.Workflow.Runtime
{
    public abstract class WorkflowActionContext : IActionExecutor
    {
        #region Instance Properties

        /// <summary>
        ///   Gets or sets the name of the action.
        /// </summary>
        /// <value>The name of the action.</value>
        public string ActionName { get; set; }

        #endregion

        #region Instance Methods

        /// <summary>
        ///   Sends the mail to sender.
        /// </summary>
        /// <param name = "sender">The sender.</param>
        /// <param name = "receiver">The receiver.</param>
        /// <param name = "object">The object.</param>
        /// <param name = "message">The message.</param>
        /// <returns></returns>
        protected virtual void SendMailToSender(User sender, User receiver, string @object, string message)
        {
            const string emailPattern = @"^(([^<>()[\]\\.,;:\s@\""]+"
                                        + @"(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))@"
                                        + @"((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
                                        + @"\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+"
                                        + @"[a-zA-Z]{2,}))$";

            if (!String.IsNullOrWhiteSpace(SettingsManager.cStoreSettings.Parameter_Smtp))
            {
                LogManager.Instance().LogWarn("Unable to send email => SMTP parameter is null");
                return;
            }

            if (!Regex.IsMatch(receiver.Email, emailPattern))
            {
                LogManager.Instance().LogWarnFormat(
                    "Unable to send email => Receiver's email cannot match with the email pattern : ID({0}) Fullname({1}) Email({2})",
                    receiver.UserId,
                    receiver.FullName,
                    receiver.Email);
                return;
            }

            if (!Regex.IsMatch(sender.Email, emailPattern))
            {
                LogManager.Instance().LogWarnFormat(
                    "Unable to send email => Sender's email cannot match with the email pattern : ID({0}) Fullname({1}) Email({2})",
                    sender.UserId,
                    sender.FullName,
                    sender.Email);
                return;
            }

            Smtp.SendMail(SettingsManager.cStoreSettings.Parameter_Smtp,
                          @object,
                          message,
                          new MailAddress(receiver.Email, ""),
                          new MailAddress(sender.Email, sender.FullName),
                          SettingsManager.cStoreSettings.Parameter_SmtpLogin,
                          SettingsManager.cStoreSettings.Parameter_SmtpPassword);
        }

        /// <summary>
        ///   Sends the mail to sender with template.
        /// </summary>
        /// <param name = "sender">The sender.</param>
        /// <param name = "receiver">The receiver.</param>
        /// <param name = "object">The object.</param>
        /// <param name = "templateMailName">Name of the template mail.</param>
        /// <param name = "templateMailCulture">The template mail culture.</param>
        /// <param name = "templateMailTokens">The template mail parameters.</param>
        protected virtual void SendMailToSenderWithTemplate(User sender,
                                                            User receiver,
                                                            string @object,
                                                            string templateMailName,
                                                            CultureInfo templateMailCulture,
                                                            List<Parameter> templateMailTokens)
        {
            try
            {
                //Build path to the mail template
                string mailPath = Path.Combine(
                    GetEnvironnementPath(),
                    ConfigurationManager.AppSettings.Get("Rio.Applications.Web.MailTemplatesDirectory"),
                    String.Format("{0}_{1}.html", templateMailName, templateMailCulture.Name));

                string mailContent = File.ReadAllText(mailPath);

                //Replace all token
                //Token format in mail : {$key}
                foreach (var item in templateMailTokens)
                {
                    mailContent = mailContent.Replace(item.ParameterName, item.ParameterValue);
                }

                SendMailToSender(sender, receiver, @object, mailContent);
            }
            catch (Exception ex)
            {
                LogManager.Instance().LogErrorFormat("Unable to send email => " + ex);
            }
        }

        /// <summary>
        ///   Sends the mail from template.
        /// </summary>
        /// <param name = "context">The context.</param>
        /// <param name = "templateMail">The template mail.</param>
        protected void SendMailFromTemplate(WorkflowContextBase context, string templateMail)
        {
            try
            {
                //Send mail
                var sender = context.CurrentInstance.Sender;
                if (!string.IsNullOrEmpty(sender.Email))
                {
                    User currentUser = UserRepository.GetUserById(context.UserId);

                    List<Parameter> parameters = new List<Parameter>
                                                     {
                                                         new Parameter("{$user}",
                                                                       String.Format("{0} {1}",
                                                                                     currentUser.FirstName ??
                                                                                     string.Empty,
                                                                                     currentUser.LastName ??
                                                                                     string.Empty)),
                                                         new Parameter("{$url}",
                                                                       ConfigurationManager.AppSettings.Get(
                                                                           "Rio.Applications.Web.Url"))
                                                     };

                    SendMailToSenderWithTemplate(
                        sender,
                        currentUser,
                        context.CurrentDefinition.Name,
                        templateMail,
                        new CultureInfo(ConfigurationManager.AppSettings.Get("Rio.Applications.Web.DefaultCulture")),
                        parameters);
                }
            }
            catch (Exception ex)
            {
                LogManager.Instance().LogErrorFormat("Unable to send email => " + ex);
            }
        }

        /// <summary>
        ///   Ventilates this instance.
        /// </summary>
        /// <param name = "context">The context.</param>
        /// <param name = "request">The request.</param>
        protected bool Ventilate(WorkflowContextBase context, ActionRequest request)
        {
            //Gets new receivers
            string newReceivers = string.Empty;
            if (context.CurrentInstance.Definition.ReceiversType
                == ReceiverType.Auto)
            {
                //Get all receivers and restart flow
                newReceivers = WorkflowInstanceRepository.GetReceivers(context.CurrentInstance.Identifier);
            }
            else
            {
                //get receivers from index 
                if (context.CurrentInstance.Definition.ReceiverIndexId != null)
                {
                    long indexid = context.CurrentInstance.Definition.ReceiverIndexId.Value;

                    var folder = FolderRepository.GetFolder(context.UserId,
                                                            request.OrganizationIdentifier,
                                                            request.FolderTypeIdentifier,
                                                            request.FolderIdentifier);
                    newReceivers = folder.IndexIdValues[indexid];
                }
            }

            //Set all document to initial state
            bool result = context.CurrentInstance.RestartWorkflowInstance(newReceivers);
            if (result)
            {
                WorkflowInstanceRepository.AddHistoricalForAllDocuments(context.OriginalInstance.Identifier,
                                                                        null,
                                                                        context.UserId,
                                                                        WorkflowState.Ventilated,
                                                                        context.CurrentAction.ActionOrConditionId);
            }
            return result;
        }

        /// <summary>
        ///   Returns the current application path for the current hosting environment
        /// </summary>
        /// <returns></returns>
        private string GetEnvironnementPath()
        {
            //bin dir
            return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        }

        #endregion

        #region IActionExecutor Members

        /// <summary>
        ///   Executes the specified WKF context.
        /// </summary>
        /// <param name = "wkfContext">The WKF context.</param>
        /// <param name = "request">The request.</param>
        /// <returns></returns>
        public abstract ActionResult ActionExecuted(WorkflowContextBase wkfContext, ActionRequest request);

        /// <summary>
        ///   Actions the executed all.
        /// </summary>
        /// <param name = "context">The context.</param>
        /// <param name = "request">The request.</param>
        /// <returns></returns>
        public abstract ActionResult ActionExecutedAll(WorkflowContextBase context, ActionRequest request);

        /// <summary>
        ///   Actions the executing.
        /// </summary>
        /// <param name = "wkfContext">The WKF context.</param>
        /// <param name = "request">The request.</param>
        /// <returns></returns>
        public abstract ActionResult ActionExecuting(WorkflowContextBase wkfContext, ActionRequest request);

        /// <summary>
        ///   Actions the executing all.
        /// </summary>
        /// <param name = "context">The context.</param>
        /// <param name = "request">The request.</param>
        /// <returns></returns>
        public abstract ActionResult ActionExecutingAll(WorkflowContextBase context, ActionRequest request);

        #endregion
    }
}